using System;
using System.Xml;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace XMLStuffs
{
    public static class XmlParser
    {

        // Generate Thread XML
        public static Byte[] ThreadToXml(Thread _Thread)
        {

            // Could the start of document etc. be moved to another func?
            // Hmm. This would allow multiple <threads> per file useful for board 
            // front pages?

            // Open XML etc. etc.
                // Make a buffered StreamWriter
                MemoryStream MS = new MemoryStream();
                StreamWriter SW = new StreamWriter(MS);
                // Open XML Document in Memory
                XmlTextWriter XML = new XmlTextWriter(SW);
                XML.WriteStartDocument();
                XML.Formatting = Formatting.Indented;
                
            // Open <thread> -- Add the attributes!
            XML.WriteStartElement("thread");
            XML.WriteAttributeString("id", _Thread.ID.ToString());
            XML.WriteAttributeString("board", _Thread.Board);

            // Posts in thread?
            if (_Thread.Posts.Count > 0)
                // Add posts
                foreach (Post P in _Thread.Posts.Values)
                    PostToXml(ref XML, P);

            // Close <thread> & Document
            XML.WriteEndElement();
            XML.WriteEndDocument();
            XML.Close();

            // Return the xml document
            return MS.ToArray();

        }

        // XML to Thread
        public static Thread XmlToThread(Byte[] Data)
        {

            // Thread var
            Thread T = new Thread();

            // XML Document
                // Streams
                MemoryStream MS = new MemoryStream(Data);
                // XML
                XmlTextReader XML = new XmlTextReader(MS);
                XML.Read();

            // Go through document till end
            while (XML.Read())
            {

                // Element?
                if (XML.NodeType == XmlNodeType.Element)
                {

                    // Thread?
                    if (XML.Name == "thread")
                    {

                        // Add the attributes
                        T.ID = Int32.Parse(XML.GetAttribute("id"));
                        T.Board = XML.GetAttribute("board");

                    }
                    
                    // Post?
                    else if (XML.Name == "post")
                        // Pass to function
                        T.AddPost(XmlToPost(ref XML));
  
                }

            }

            // Return the thread
            return T;

        }

        // Generate Post XML
        public static void PostToXml(ref XmlTextWriter XML, Post _Post)
        {

            // Start
            XML.WriteStartElement("post");
            XML.WriteAttributeString("id", _Post.ID.ToString());
            XML.WriteAttributeString("image", _Post.HasImage.ToString());

            // Meta Data
                // Start
                XML.WriteStartElement("metadata");
                // Do each meta item
                foreach (MetaItem Item in _Post.MetaData.Items.Values)
                {

                    // Write name & value
                    XML.WriteStartElement("metaitem");
                    XML.WriteAttributeString("name", Item.Name);
                    XML.WriteAttributeString("value", Item.Value);
                    XML.WriteEndElement();

                }
                // End
                XML.WriteEndElement();

            // Text
            XML.WriteStartElement("text");
            XML.WriteCData(_Post.Text);
            XML.WriteEndElement();

            // End
            XML.WriteEndElement();

        }
        public static byte[] PostToXml(Post _Post)
        {

            // Variables
            MemoryStream MS = new MemoryStream();
            StreamWriter SW = new StreamWriter(MS);
            XmlTextWriter XML = new XmlTextWriter(SW);

            // Not that I really know how to use an XmlTextWriter, but oh well
            PostToXml(ref XML, _Post);

            // Clean-up our shite...
            XML.Close();
            SW.Close();
            XML = null;
            SW = null;

            // Aaaaand return a byte[]. ^^
            return MS.ToArray();

        }

        // XML to Post
        public static Post XmlToPost(ref XmlTextReader XML)
        {

            // Vars
            Post P = new Post();

            // Only parse the <post>
            while (!((XML.NodeType == XmlNodeType.EndElement) && (XML.Name == "post")))
            {   

                // Element?
                if (XML.NodeType == XmlNodeType.Element)
                {

                    // Do something depending on the element
                    switch (XML.Name)
                    {

                        // <post>
                        case "post":

                            // We need to parse this to get id and stuff
                            P.ID = Int32.Parse(XML.GetAttribute("id"));
                            P.HasImage = Boolean.Parse(XML.GetAttribute("image"));

                            break;

                        // <metadata>
                        case "metadata":

                            // Go through each metaitem till </metadata
                            while (!((XML.NodeType == XmlNodeType.EndElement) && (XML.Name == "metadata")))
                            {

                                // <metaitem>?
                                if ((XML.NodeType == XmlNodeType.Element) && (XML.Name == "metaitem"))
                                    P.AddMetaItem(XML.GetAttribute("name"), XML.GetAttribute("value"));

                                XML.Read();

                            }

                            break;

                        // <text>
                        case "text":

                            // Add text
                            P.Text = XML.ReadString();

                            break;

                    }

                }

                // Read
                XML.Read();

            }

            // Return the Post
            return P;

        }
        public static Post XmlToPost(byte[] XMLData)
        {

            // Variables
            MemoryStream MS = new MemoryStream(XMLData);
            XmlTextReader XML = new XmlTextReader(MS);

            // Call daddy!
            return XmlToPost(ref XML);

        }

    }
}
